using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.Office.Server.ActivityFeed;
using System.Security.Principal;
using Microsoft.Office.Server.UserProfiles;
using eGov.SharePoint.MyPeeps.EventReceivers;
using Microsoft.SharePoint.Administration;
using System.Collections.ObjectModel;
using System.Web;
using System.Diagnostics;
using eGov.SharePoint.MyPeeps.Properties;
using System.Reflection;


namespace eGov.SharePoint.MyPeeps.Features.MySiteStapler
{
    /// <summary>
    /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
    /// </summary>
    /// <remarks>
    /// The GUID attached to this class may be used during packaging and should not be modified.
    /// </remarks>

    [Guid("284147e6-5dc2-4a13-9da3-970153e21c3d")]
    public class MySiteStaplerEventReceiver : SPFeatureReceiver
    {
        string ActivityResourceFile = "EGOV_CustomFeeds";
        string ActivityApplicationTitle_TweetUpdate = "ActivityApplicationTitle_TweetUpdate";
        string ActivityTitle_TweetUpdate = "ActivityName_TweetUpdate";
        string ActivityTemplateTitle_TweetUpdate = "ActivityTemplate_TweetUpdate";
        string ActivityTitle_FacebookUpdate = "ActivityName_FacebookUpdate";
        string ActivityTemplateTitle_FacebookUpdate = "ActivityTemplate_FacebookUpdate";

        // Uncomment the method below to handle the event raised before a feature is activated.
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {

            SPWebApplication myApp = properties.Feature.Parent as SPWebApplication;
            Guid mySiteHostSiteGuid = Guid.Empty;
            EventLog eventlog = new EventLog();

            foreach (SPSite site in myApp.Sites)
            {
                if (site.RootWeb.WebTemplate == "SPSMSITEHOST")
                {
                    mySiteHostSiteGuid = site.ID;
                    break;
                }
            }

            eventlog.Source = "MySite Stapler Feature - Web Config Changes";
            try
            {
                eventlog.WriteEntry("Starting Web Config Changes");
                EnsureWebConfigChanges(properties);
                eventlog.WriteEntry("Successfully implemented Web Config Changes");
            }
            catch (Exception ex)
            {
                eventlog.WriteEntry("Error in Web Config Changes" + ex.StackTrace + " " + ex.Source + " " + ex.ToString());
            }

            eventlog.Source = "MySite Stapler Feature - activity Stream Registration";
            try
            {
                eventlog.WriteEntry("Starting Custom Activity Stream Settings Registration");
                RegisterActivityStreamSettings(mySiteHostSiteGuid);
                eventlog.WriteEntry("Successfully Registered Custom Activity Stream settings");
            }
            catch (Exception ex)
            {
                eventlog.WriteEntry("Error inActivity Stream Registration" + ex.StackTrace + " " + ex.Source + " " + ex.ToString());
                throw ex;
            }

            eventlog.WriteEntry("Successfully Activated Stapler Feature - no errors encountered");
        }


        public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        {
            //ActivityManager activityManager = null;

            //try
            //{
            //    activityManager = new ActivityManager();
            //    ActivityApplication actApplication_eGovFeeds = null;

            //    if (activityManager.PrepareToAllowSchemaChanges())
            //    {
            //        /// Register feed application type
            //        if (activityManager.ActivityApplications[ActivityApplicationTitle_TweetUpdate] == null)
            //        {
            //            actApplication_eGovFeeds = activityManager.ActivityApplications.Create(ActivityApplicationTitle_TweetUpdate);
            //            actApplication_eGovFeeds.Commit();
            //            actApplication_eGovFeeds.Refresh(true);
            //        }
            //        else actApplication_eGovFeeds = activityManager.ActivityApplications[ActivityApplicationTitle_TweetUpdate];

            //        /// Register feed types
            //        ActivityType actType_TweeterUpdate = RegisterActivityTypes(actApplication_eGovFeeds, ActivityTitle_TweetUpdate);
            //        ActivityType actType_FacebookUpdate = RegisterActivityTypes(actApplication_eGovFeeds, ActivityTitle_FacebookUpdate);

            //        /// Register feed rendering templates
            //        RegisterActivityTemplateTypes(actType_TweeterUpdate, ActivityTemplateTitle_TweetUpdate);
            //        RegisterActivityTemplateTypes(actType_TweeterUpdate, ActivityTemplateTitle_FacebookUpdate);
            //    }
            //}
            //catch (Exception ex)
            //{
            //    // log
            //    // dont allow feature to install/activate
            //    //throw new SPException("", ex);
            //}
            //finally
            //{
            //    if (activityManager != null) activityManager.Dispose();
            //}
        }

        public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        {

            //ActivityManager activityManager = null;
            //try
            //{
            //    activityManager = new ActivityManager();

            //    if (activityManager.PrepareToAllowSchemaChanges())
            //    {
            //        ActivityApplication actApplication_eGovFeeds = activityManager.ActivityApplications[ActivityApplicationTitle_TweetUpdate];
            //        if (actApplication_eGovFeeds != null) ;
            //        /// Method not implemented on API
            //        /// actApplication_eGovFeeds.Remove();
            //    }
            //}
            //catch (Exception ex)
            //{
            //    // log
            //    // dont allow feature to install/activate
            //    //throw new SPException("Feature failed to uninstall. Exception: " + ex.Message, ex);
            //}
            //finally
            //{
            //    if (activityManager != null) activityManager.Dispose();
            //}

        }

        #region Helper Methods

        private void EnsureWebConfigChanges(SPFeatureReceiverProperties properties)
        {
            EventLog eventlog = new EventLog();
            eventlog.Source = "MySite Customization Feature - Web Config Changes";

            if (SPContext.Current == null || SPContext.Current.Site == null) return;

            Guid SPSiteGuid = SPContext.Current.Site.ID;

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                //using (SPSite site = new SPSite(SPSiteGuid))
                //{

                //HttpContext currentContext = HttpContext.Current;
                try
                {
                    #region web.config modification
                    bool flag = false;
                    SPWebApplication webApplication = properties.Feature.Parent as SPWebApplication;
                    Collection<SPWebConfigModification> oCollection = webApplication.WebConfigModifications;
                    foreach (SPWebConfigModification oModification in oCollection)
                        if (oModification.Owner == properties.Feature.DefinitionId.ToString())
                        {
                            flag = true;
                            break;
                        }

                    if (flag == false)
                    {
                        eventlog.WriteEntry("Starting Web Config Changes");
                        foreach (ModificationEntry entry in Entries)
                        {
                            webApplication.WebConfigModifications.Add(CreateModification(entry.Name, entry.XPath, entry.Value, properties.Feature.DefinitionId));
                        }

                        webApplication.Update(true);
                        webApplication.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
                        eventlog.WriteEntry("Done web.config changes by Site Stapler Feature");
                    }
                    #endregion
                }
                catch (Exception e)
                {
                    eventlog.WriteEntry(String.Format("Error Post-Installing MySite Customization feature {0} : ", e.ToString()), EventLogEntryType.Error);
                }
                //}
            });

        }

        private class ModificationEntry
        {
            public string Name { get; set; }
            public string XPath { get; set; }
            public string Value { get; set; }
            public ModificationEntry(string Name, string XPath, string Value)
            {
                this.Name = Name;
                this.XPath = XPath;
                this.Value = Value;
            }
        }

        private ModificationEntry[] Entries = new ModificationEntry[]
         {
               new ModificationEntry(
                   "add[@key='WhatsOnYourMindExternalUpdates']",
                   "configuration/appSettings",
                   @"<add key=""WhatsOnYourMindExternalUpdates"" value=""True""/>"
                   ),
                     new ModificationEntry(
                   "add[@key='FacebookAPIkey']",
                   "configuration/appSettings",
                   @"<add key=""FacebookAPIkey"" value=""" + Properties.Settings.Default.FacebookAPIkey  + "\" />"
                   ),
                     new ModificationEntry(
                   "add[@key='FacebookSECRET']",
                   "configuration/appSettings",
                   @"<add key=""FacebookSECRET"" value=""" + Properties.Settings.Default.FacebookSECRET + "\" />"
                   ),
         };

        private static SPWebConfigModification AddAppSettings(Guid ownerId)
        {
            SPWebConfigModification configMod = new SPWebConfigModification();

            configMod = new SPWebConfigModification();
            configMod.Name = @"appSettings";
            configMod.Path = "configuration";
            configMod.Sequence = 0;
            configMod.Owner = ownerId.ToString();
            configMod.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureSection;
            configMod.Value = "<appSettings />";

            return configMod;
        }

        private static SPWebConfigModification CreateModification(string name, string xpath, string value, Guid owner)
        {
            SPWebConfigModification modification = new SPWebConfigModification(name, xpath);
            modification.Owner = owner.ToString();
            modification.Sequence = 0;
            modification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
            modification.Value = value;

            return modification;
        }


        #endregion

        #region Activity Stream settings registration

        protected void RegisterActivityStreamSettings(Guid mySiteHostSiteGuid)
        {
            if (SPContext.Current == null || SPContext.Current.Site == null) return;

            //Guid SPSiteGuid = SPContext.Current.Site.ID;

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite Site = new SPSite(mySiteHostSiteGuid))
                {
                    HttpContext currentContext = HttpContext.Current;
                    try
                    {
                        HttpContext.Current = null;
                        SPServiceContext spContext = SPServiceContext.GetContext(Site);

                        UserProfileManager userManager = new UserProfileManager(spContext);
                        string accPoolProfileName = WindowsIdentity.GetCurrent().Name;
                        UserProfile accPoolProfile = null;
                        if (userManager.UserExists(accPoolProfileName)) accPoolProfile = userManager.GetUserProfile(accPoolProfileName);
                        else userManager.CreateUserProfile(accPoolProfileName);

                        ActivityManager activityManager = new ActivityManager(accPoolProfile, spContext);

                        ActivityApplication actApplication_eGovFeeds = null;

                        if (activityManager.PrepareToAllowSchemaChanges())
                        {
                            /// Register feed application type
                            if (activityManager.ActivityApplications[Settings.Default.ActivityApplicationTitle_eGovCustomFeeds] == null)
                            {
                                actApplication_eGovFeeds = activityManager.ActivityApplications.Create(Settings.Default.ActivityApplicationTitle_eGovCustomFeeds);
                                actApplication_eGovFeeds.Commit();
                                actApplication_eGovFeeds.Refresh(true);
                            }
                            else actApplication_eGovFeeds = activityManager.ActivityApplications[Settings.Default.ActivityApplicationTitle_eGovCustomFeeds];

                            /// Register feed types
                            ActivityType actType_TweeterUpdate = RegisterActivityTypes(actApplication_eGovFeeds, Settings.Default.ActivityTitle_TweetUpdate);
                            ActivityType actType_FacebookUpdate = RegisterActivityTypes(actApplication_eGovFeeds, Settings.Default.ActivityTitle_FacebookUpdate);

                            ActivityType actType_ContentModify = RegisterActivityTypes(actApplication_eGovFeeds, Settings.Default.ActivityTitle_ContentModify);
                            ActivityType actType_ContentDelete = RegisterActivityTypes(actApplication_eGovFeeds, Settings.Default.ActivityTitle_ContentDelete);
                            ActivityType actType_ContentNew = RegisterActivityTypes(actApplication_eGovFeeds, Settings.Default.ActivityTitle_ContentNew);

                            /// Register feed rendering templates
                            RegisterActivityTemplateTypes(actType_TweeterUpdate, Settings.Default.ActivityTemplateTitle_TweetUpdate);
                            RegisterActivityTemplateTypes(actType_FacebookUpdate, Settings.Default.ActivityTemplateTitle_FacebookUpdate);

                            RegisterActivityTemplateTypes(actType_ContentModify, Settings.Default.ActivityTemplateTitle_ContentModify);
                            RegisterActivityTemplateTypes(actType_ContentDelete, Settings.Default.ActivityTemplateTitle_ContentDelete);
                            RegisterActivityTemplateTypes(actType_ContentNew, Settings.Default.ActivityTemplateTitle_ContentNew);
                        }

                        /// Force Clear Cache
                        try
                        {
                            System.Reflection.PropertyInfo propUserProfileApplicationProxy = typeof(ActivityManager).GetProperty("UserProfileApplicationProxy", BindingFlags.Instance | BindingFlags.NonPublic);
                            object objUserProfileApplicationProxy = propUserProfileApplicationProxy.GetValue(activityManager, null);
                            //Getting the method information using the method info class
                            MethodInfo mi = objUserProfileApplicationProxy.GetType().GetMethod("ClearDataCache", new Type[] { typeof(Guid) });
                            mi.Invoke(objUserProfileApplicationProxy, new object[] { activityManager.PartitionID });
                        }
                        catch { }

                        if (activityManager != null) activityManager.Dispose();
                    }
                    catch (UnauthorizedAccessException securityEx)
                    {
                        throw securityEx;
                        //logService.WriteTrace(100, logCategory_Error, TraceSeverity.High,
                        //String.Format(@"Failed to create custom activity feed. Make sure application pool account have admin permissions for the user profile service.
                        //Exception message: {0} \r\n Stack Trace: \r\n {1}", new object[] { securityEx.Message, securityEx.StackTrace }), null);
                    }
                    catch (SPException sharepointEx)
                    {
                        throw sharepointEx;
                        //logService.WriteTrace(100, logCategory_Error, TraceSeverity.High,
                        //String.Format("Failed to create custom activity feed. Exception message: {0} \r\n Stack Trace: \r\n {1}", new object[] { sharepointEx.Message, sharepointEx.StackTrace }), null);
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                    finally
                    {
                        HttpContext.Current = currentContext;
                    }
                }
            });
        }

        internal ActivityType RegisterActivityTypes(ActivityApplication actApplication, string ActivityTitle)
        {
            ActivityType actType = null;
            if (actApplication.ActivityTypes[ActivityTitle] == null)
            {
                actType = actApplication.ActivityTypes.Create(ActivityTitle);
                actType.ActivityTypeNameLocStringName = ActivityTitle;
                actType.ActivityTypeNameLocStringResourceFile = Settings.Default.ActivityStreamResourceFile;
                actType.IsPublished = true;
                actType.IsConsolidated = true;
                actType.AllowRollup = true;
                actType.Commit();
                actType.Refresh(true);
            }
            else actType = actApplication.ActivityTypes[ActivityTitle];
            return actType;
        }

        internal void RegisterActivityTemplateTypes(ActivityType actType, string ActivityTemplateTitle)
        {
            if (actType.ActivityTemplates[ActivityTemplatesCollection.CreateKey(false)] == null)
            {
                ActivityTemplate actTemplate = null;
                /// Create feed rendering template
                actTemplate = actType.ActivityTemplates.Create(false);
                actTemplate.TitleFormatLocStringResourceFile = Settings.Default.ActivityStreamResourceFile;
                actTemplate.TitleFormatLocStringName = ActivityTemplateTitle;
                actTemplate.Commit();
            }
        }

        #endregion

    }

}
